home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / blankery / agblankers / source / water / blank.c next >
C/C++ Source or Header  |  1995-03-22  |  11KB  |  371 lines

  1. /* Water blanker
  2.  *
  3.  * written 13.-14.02.95, Karlheinz Agsteiner
  4.  * Based on the dragon blanker 
  5.  *
  6.  * This blanker uses some hacks (which don't break our code, of course)
  7.  * 1. unsigned integers are used in function Water() to represent coordinates.
  8.  *    This has consequences:
  9.  *    negative coordinates can occur, ie. overflows take place.
  10.  *    This is actually good for us since our clipping gets easier:
  11.  *     signed: if (x>=0 && x <= width), unsigned: if (x <= width)
  12.  * 2. Constants are set nicely (VARIATIONS=32 allows SAS/C to 
  13.  *    replace a[i][j]=a+i*VARIATIONS+j by a+SomeShiftsAndAdds(i)+j
  14.  * 3. Instead of coloring every dot perfectly with color
  15.  *    variation*colors/<max.variation for this point> we color it 
  16.  *    with variation*colors/<limit of variations>.
  17.  *    This is only an approximation and in some cases (when the
  18.  *    dots "drop" out of the screen) too few colors are used.
  19.  *    But it allows us to precompute this and replace a multiplication
  20.  *    plus division by one array access.
  21.  *    Our new approximation is much better, btw. It uses instead of
  22.  *    the theoretical limit the longest path actually reached by a
  23.  *    drop. Since the paths are roughly of the same length this is
  24.  *    nearly perfect.
  25.  * Altogether, our core loop in Water() only uses some moves, shifts,
  26.  * adds, subs and jumps but nothing else. */
  27.  
  28. /* V1.0: 14.02.95 (initial version)
  29.  * V1.1: 11.03.95 Bugfix: When the blanker was aborted in the initialization
  30.  *       routine the blank() function returned too late causing access to
  31.  *       uninitialized data. Bug found by Roberto Patriarca */
  32.  
  33. #include <exec/memory.h>
  34. #include <math.h>
  35. #include <stdlib.h>
  36.  
  37. #include "/includes.h"
  38.  
  39. #define FLOATRAND() (((double)RangeRand(10000))/10000)
  40.  
  41. #define bool int
  42. #define TRUE 1
  43. #define FALSE 0
  44.  
  45. #define STAGES     100
  46. #define VARIATIONS 32
  47. #define XOFFMAX    50
  48. #define YOFFMAX    10
  49. #define ZEIT       800
  50.  
  51. #define USEUNSIGNED    /* use unsigned instead of signed (hack 1) */
  52. #define ESTIMATE        /* estimate the colors instead of using their real 
  53.                          * values (hack 3) */
  54. /*#define FASTBACK*/    /* don't compute new random paths and coords when 
  55.                          * the drop reaches bottom */
  56.  
  57. #define LIMIT -10000000
  58.  
  59. Triplet *ColorTable = 0L;
  60.  
  61. #ifdef USEUNSIGNED
  62. #define integer unsigned int
  63. #else
  64. #define integer int
  65. #endif
  66.  
  67. typedef struct { integer x,y; } vector;
  68. typedef struct { int x,y; } signedvector;
  69.  
  70. signedvector pattern[VARIATIONS][STAGES];
  71. unsigned int maxstage[VARIATIONS];
  72. vector       *point = NULL; /* [POINTS] */
  73. unsigned int *thepattern = NULL; /* [POINTS] */
  74. unsigned int *thestage = NULL; /* [POINTS] */
  75.  
  76. #ifdef ESTIMATE
  77. int stagecolor[STAGES];
  78. #endif
  79.  
  80. #define DROPS 0
  81. #define TIME  2
  82. #define MODE  4
  83.  
  84.  
  85. VOID Defaults( PrefObject *Prefs )
  86. {
  87.   Prefs[DROPS].po_Level = 600;     
  88.   Prefs[TIME].po_Level = 400;
  89.   Prefs[MODE].po_ModeID = getTopScreenMode();
  90.   Prefs[MODE].po_Depth = 4;
  91. }
  92.  
  93.  
  94. LONG init_structure(int width, int height, int points, int *maxoffset)
  95. { int var,stage,thepoint,xwidth;
  96.   bool onedir,whichdir,dropout,dropdown;
  97.   double vyoff,vxoff,axoff,ymax;
  98.   LONG flg_end;
  99.   onedir = (bool)RangeRand(2);
  100.   whichdir = (bool)RangeRand(2);
  101.   
  102.   if (RangeRand(2))
  103.     vyoff = -25*FLOATRAND();
  104.   else
  105.     vyoff = 0;
  106.   vxoff = (double)RangeRand(5);
  107.   axoff = FLOATRAND()*0.5;
  108.   ymax = (double)RangeRand(10)+500.0;
  109.   dropout = (bool)RangeRand(2);
  110.   dropdown = (bool)RangeRand(2);
  111.  
  112.   /* Compute VARIATIONS patterns of STAGES stages each */
  113.   for (var = 0; var < VARIATIONS; var++)
  114.     { double ax,ay,vx,vy,x,y;
  115.       bool   finished;
  116.  
  117.       flg_end = ContinueBlanking();
  118.       if (flg_end != OK)
  119.     { return flg_end; }
  120.  
  121.       ax = 0; ay = FLOATRAND()*0.2+axoff+0.2;
  122.       if (onedir)
  123.     { vx = FLOATRAND()*3+vxoff;
  124.         }
  125.       else
  126.         vx = FLOATRAND()*6-3;
  127.       if (whichdir)
  128.         vx = -1*vx;
  129.  
  130.       vy = -1*(FLOATRAND()*3)+vyoff;
  131.       x = 0; y = 0;
  132.       finished = FALSE;
  133.       stage = 0;
  134.       while (stage < STAGES && !finished)
  135.         { x = x + vx;
  136.           y = y + vy;
  137.           if (y > ymax)
  138.             { if (dropout)
  139.                 { if (!dropdown) finished = TRUE;
  140.                 }
  141.               else
  142.                 { y = y - vy;
  143.                   vy = - vy/2;
  144.                   x = x - 3*vx;
  145.                 }
  146.             }
  147.           vx = vx + ax;
  148.           vy = vy + ay;
  149.           if (finished)
  150.             { pattern[var][stage].x = LIMIT;
  151.               maxstage[var] = stage-1;
  152.             }
  153.           else
  154.             { pattern[var][stage].x = (int)x;
  155.               pattern[var][stage].y = (int)y;
  156.             }
  157.           stage++;
  158.         }
  159.       if (!finished)
  160.     { maxstage[var] = STAGES;
  161.     }
  162.     }
  163.  
  164.   /* Normalize the resulting patterns */
  165.   /*   first: find the limits */
  166.   { int minx,maxx,miny,maxy,counter;
  167.     minx = pattern[0][0].x; maxx = pattern[0][0].x;
  168.     miny = pattern[0][0].y; maxy = pattern[0][0].y;
  169.     for (var=0; var<VARIATIONS; var++)
  170.       { stage=0;
  171.         while (stage<STAGES && stage <= maxstage[var])
  172.           { if (minx>pattern[var][stage].x)
  173.               minx = pattern[var][stage].x;
  174.             if (miny>pattern[var][stage].y)
  175.               miny = pattern[var][stage].y;
  176.             if (maxx<pattern[var][stage].x)
  177.               maxx = pattern[var][stage].x;
  178.             if (maxy<pattern[var][stage].y)
  179.               maxy = pattern[var][stage].y;
  180.             stage++;
  181.           }
  182.       }
  183.    
  184.    /*  then: transform [minx..maxx] -> [0..width], y -> [0..height] */
  185.    xwidth = RangeRand(width-10)+10;
  186.    *maxoffset = width-xwidth;
  187.    for (var=0; var<VARIATIONS; var++)
  188.      { stage = 0;
  189.        while (stage<STAGES && stage <= maxstage[var])
  190.          { pattern[var][stage].x = ((pattern[var][stage].x-minx)*xwidth)/(maxx-minx);
  191.            pattern[var][stage].y = ((pattern[var][stage].y-miny)*height)/(maxy-miny);
  192.            stage++;
  193.          }
  194.      }
  195.        
  196.    /* Define the points (initial offset, variation, stage) */
  197.    counter = 0;
  198.    for (thepoint = 0; thepoint < points; thepoint++)
  199.      { point[thepoint].x = RangeRand(20)-10;
  200.        point[thepoint].y = RangeRand(10)-5;
  201.        thepattern[thepoint] = RangeRand(VARIATIONS);
  202.        thestage[thepoint] = RangeRand(maxstage[thepattern[thepoint]]);
  203.        counter++;
  204.        if (counter == 100)
  205.          { flg_end = ContinueBlanking();
  206.            if (flg_end != OK)
  207.          { return flg_end; }
  208.            counter = 0;
  209.          }
  210.      }
  211.   }
  212.   return OK;
  213. }
  214.           
  215.  
  216.  
  217. LONG Water( struct Screen *Scr, SHORT Width, SHORT Height, unsigned int points, unsigned int time)
  218. { LONG flg_end;
  219.   unsigned int Wid=Width;
  220.   unsigned int Hei=Height;
  221.   unsigned int i,k,offset;
  222.   struct RastPort *rp = &( Scr->RastPort );
  223.   int colors;
  224.  
  225.   /* Initialize dynamic data structures */
  226.   point = malloc(points * sizeof(vector));
  227.   if (point == NULL) return FAILED;
  228.   thepattern = malloc(points * sizeof(unsigned int));
  229.   if (thepattern == NULL) return FAILED;
  230.   thestage = malloc(points * sizeof(unsigned int));
  231.   if (thestage == NULL) return FAILED;
  232.  
  233.   colors = (1L << Scr->BitMap.Depth);
  234.  
  235.   do { flg_end = init_structure(Wid,Hei,points,&offset);
  236.        if (flg_end != OK)
  237.          { free(thestage);
  238.        free(thepattern);
  239.        free(point);
  240.        return flg_end;
  241.          }
  242.        
  243. #    ifdef ESTIMATE
  244.        { unsigned int i,maxst;
  245.          maxst = 0;
  246.          for (i=0; i<VARIATIONS; i++)
  247.            { if (maxst < maxstage[i])
  248.                 maxst = maxstage[i];
  249.            }
  250.          for (i=0; i<STAGES; i++)
  251.            { stagecolor[i] = i*colors/maxst;
  252.              if (stagecolor[i] == 0) stagecolor[i]=1;
  253.            }
  254.        }
  255. #    endif
  256.        offset = RangeRand(offset);
  257.        for (k=0; k<time; k++)
  258.          { for (i=0; i<points; i++)
  259.              { integer xoff = point[i].x;
  260.                integer yoff = point[i].y;
  261.                unsigned int whichpat = thepattern[i];
  262.                unsigned stage = thestage[i];
  263.                integer x = xoff + (integer)pattern[whichpat][stage].x + offset;
  264.                integer y = yoff + (integer)pattern[whichpat][stage].y;
  265. #            ifndef ESTIMATE
  266.            unsigned int mswp = maxstage[whichpat];
  267. #            endif
  268.                stage++;
  269.                SetAPen(rp,0);
  270. #            ifdef USEUNSIGNED
  271.                if (x < Wid && y < Hei)
  272. #            else
  273.                if (x >= 0 && y >= 0 && x < Wid && y < Hei) 
  274. #            endif
  275.                  WritePixel(rp,x,y);
  276. #            ifdef ESTIMATE
  277.                if (stage >=maxstage[whichpat])
  278. #            else
  279.                if (stage >= mswp)
  280. #            endif
  281.                  { 
  282. #                ifndef FASTBACK
  283.                    thepattern[i] = RangeRand(VARIATIONS);
  284. #                endif
  285.                    thestage[i]   = 0;
  286. #                ifndef FASTBACK
  287.                    point[i].x = RangeRand(20)-10;
  288.                    point[i].y = RangeRand(10)-5;
  289. #                endif
  290.                  }
  291.                else
  292.                  { thestage[i] = stage;
  293.                    x = xoff + (integer)pattern[whichpat][stage].x + offset;
  294.                    y = yoff + (integer)pattern[whichpat][stage].y;
  295. #                ifdef ESTIMATE
  296.                    SetAPen(rp,stagecolor[stage]);
  297. #                else
  298.                    SetAPen(rp,(stage*colors)/mswp);
  299. #                endif
  300. #                ifdef USEUNSIGNED
  301.                    if (x < Wid && y < Hei)
  302. #                else
  303.                    if (x >= 0 && y >= 0 && x < Wid && y < Hei) 
  304. #                endif
  305.                      WritePixel(rp,x,y);
  306.                  }
  307.              }
  308.            ScreenToFront( Scr );
  309.            flg_end = ContinueBlanking();
  310.            if (flg_end != OK) 
  311.          { free(thestage);
  312.            free(thepattern);
  313.            free(point);
  314.            return flg_end;
  315.          }
  316.          }
  317.        SetRast(rp,0);
  318.      } while (flg_end == OK);
  319.   free(thestage);
  320.   free(thepattern);
  321.   free(point);
  322.   return OK;
  323. }
  324.  
  325.  
  326.  
  327. LONG Blank( PrefObject *Prefs )
  328. {
  329.     struct Screen *Scr;
  330.     struct Window *Wnd;
  331.     LONG RetVal;
  332.         int colors;
  333.     
  334.     if( Scr = OpenScreenTags( NULL, SA_Depth, Prefs[MODE].po_Depth,
  335.                              SA_Quiet, TRUE, SA_DisplayID, Prefs[MODE].po_ModeID,
  336.                              SA_Behind, TRUE, SA_Overscan, OSCAN_STANDARD,
  337.                              TAG_DONE ))
  338.     {
  339.         SetRGB4(&( Scr->ViewPort ), 0, 0, 0, 0 );
  340.                 colors = (1 << Prefs[MODE].po_Depth);
  341.         if (colors <= 32)
  342.           { int max = 7;
  343.                     int i;
  344.             for (i=1; i<colors; i++)
  345.               { SetRGB4(&( Scr->ViewPort ), i, (max*i)/colors+8,(max*i)/colors+8,15);
  346.                       } 
  347.                   }
  348.                 else
  349.                   { int max = 127;
  350.                     int i;
  351.             for (i=1; i<colors; i++)
  352.               { SetRGB32(&( Scr->ViewPort ), i, 256*256*256*((max*i)/colors+128),
  353.                                                         256*256*256*((max*i)/colors+128),256*256*256*255);
  354.                       } 
  355.                   }
  356.         Wnd = BlankMousePointer( Scr );
  357.         
  358.         do
  359.             RetVal = Water( Scr, Scr->Width, Scr->Height , Prefs[DROPS].po_Level,
  360.                             Prefs[TIME].po_Level);
  361.         while( RetVal == OK );
  362.         
  363.         UnblankMousePointer( Wnd );
  364.         CloseScreen( Scr );
  365.     }
  366.     else
  367.         RetVal = FAILED;
  368.     
  369.     return RetVal;
  370. }
  371.